home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 May / EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso / ghost / gs403src_amiga.lha / gs4.03 / gp_amiga.c < prev    next >
C/C++ Source or Header  |  1997-04-18  |  22KB  |  903 lines

  1. /* Copyright (C) 1989, 1992, 1993, 1994 Aladdin Enterprises.  All rights reserved.
  2.  
  3.   This file is part of Aladdin Ghostscript.
  4.  
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.  
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gp_amiga.c */
  20. /* Amiga-specific routines for Ghostscript */
  21. #include <dos/dosextens.h>
  22. #include <graphics/gfxbase.h>
  23. #include <intuition/intuitionbase.h>
  24.  
  25. #include <proto/dos.h>
  26. #include <proto/exec.h>
  27.  
  28. #include "dirent_.h"
  29. #include "stat_.h"
  30. #include "string_.h"
  31. #include "time_.h"
  32. #include "gx.h"
  33. #include "gp.h"
  34. #include "gsexit.h"
  35. #include "gsstruct.h"
  36. #include "gsutil.h"
  37.  
  38. #include <signal.h>
  39. #include <stdlib.h>
  40. #include <unistd.h>
  41. #include <sys/param.h>    /* for MAXPATHLEN */
  42.  
  43. #if defined(mc68020)
  44.  #ifdef __HAVE_68881__
  45.   STATIC STRPTR VersTag = "$VER: gs 4.03 (23.09.96) MC68020/FPU version\r\n";
  46.  #else
  47.   STATIC STRPTR VersTag = "$VER: gs 4.03 (23.09.96) MC68020 version\r\n";
  48.  #endif    /* __HAVE_68881__ */
  49. #elif defined(mc68030)
  50.  #ifdef __HAVE_68881__
  51.   STATIC STRPTR VersTag = "$VER: gs 4.03 (23.09.96) MC68030/FPU version\r\n";
  52.  #else
  53.   STATIC STRPTR VersTag = "$VER: gs 4.03 (23.09.96) MC68030 version\r\n";
  54.  #endif    /* __HAVE_68881__ */
  55. #elif defined(mc68040)
  56.  #ifdef __HAVE_68881__
  57.   STATIC STRPTR VersTag = "$VER: gs 4.03 (23.09.96) MC68040/FPU version\r\n";
  58.  #else
  59.   STATIC STRPTR VersTag = "$VER: gs 4.03 (23.09.96) MC68040 version\r\n";
  60.  #endif    /* __HAVE_68881__ */
  61. #elif defined(mc68060)
  62.  #ifdef __HAVE_68881__
  63.   STATIC STRPTR VersTag = "$VER: gs 4.03 (23.09.96) MC68060/FPU version\r\n";
  64.  #else
  65.   STATIC STRPTR VersTag = "$VER: gs 4.03 (23.09.96) MC68060 version\r\n";
  66.  #endif    /* __HAVE_68881__ */
  67. #else
  68. STATIC STRPTR VersTag = "$VER: gs 4.03 (23.09.96)\r\n";
  69. #endif    /* mc68020 */
  70.  
  71. struct IntuitionBase    *IntuitionBase;
  72. struct GfxBase        *GfxBase;
  73. struct Library        *LayersBase,
  74.             *IFFParseBase,
  75.             *AslBase,
  76.             *UtilityBase;
  77. /*struct DosLibrary *DOSBase;
  78. struct MathIEEEBase *MathIeeeDoubBasBase;*/
  79.  
  80. /* Cleanup routine, as called by atexit() trap */
  81. void
  82. cleanup(void)
  83. {
  84.     extern void devcleanup(void);
  85.  
  86.     devcleanup();
  87.  
  88.     if(IFFParseBase)
  89.     {
  90.         CloseLibrary(IFFParseBase);
  91.  
  92.         IFFParseBase = NULL;
  93.     }
  94.  
  95.     if(AslBase)
  96.     {
  97.         CloseLibrary(AslBase);
  98.  
  99.         AslBase = NULL;
  100.     }
  101.  
  102.     if(UtilityBase)
  103.     {
  104.         CloseLibrary(UtilityBase);
  105.  
  106.         UtilityBase = NULL;
  107.     }
  108.  
  109.     if(LayersBase)
  110.     {
  111.         CloseLibrary(LayersBase);
  112.  
  113.         LayersBase = NULL;
  114.     }
  115.  
  116.     if(GfxBase)
  117.     {
  118.         CloseLibrary((struct Library *)GfxBase);
  119.  
  120.         GfxBase = NULL;
  121.     }
  122.  
  123.     if(IntuitionBase)
  124.     {
  125.         CloseLibrary((struct Library *)IntuitionBase);
  126.  
  127.         IntuitionBase = NULL;
  128.     }
  129. }
  130.  
  131. void
  132. signal_handler(int signal)
  133. {
  134.     fprintf(stderr,"*** BREAK: Ghostscript\a\n");
  135.  
  136.     gs_exit(1);
  137. }
  138.  
  139. /* Do platform-dependent initialization. */
  140. void
  141. gp_init(void)
  142. {
  143.     atexit(cleanup);
  144.  
  145.     signal(SIGINT,signal_handler);
  146.     
  147.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
  148.     {
  149.         eprintf("Ghostscript: cannot open intuition.library v37\n");
  150.  
  151.         exit(20);
  152.     }
  153.     
  154.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
  155.     {
  156.         eprintf("Ghostscript: cannot open graphics.library v37\n");
  157.  
  158.         exit(20);
  159.     }
  160.  
  161.     if(!(LayersBase = OpenLibrary("layers.library",37)))
  162.     {
  163.         eprintf("Ghostscript: cannot open layers.library v37\n");
  164.  
  165.         exit(20);
  166.     }
  167.  
  168.     if(!(UtilityBase = OpenLibrary("utility.library",37)))
  169.     {
  170.         eprintf("Ghostscript: cannot open utility.library v37\n");
  171.  
  172.         exit(20);
  173.     }
  174.  
  175.     if(!(IFFParseBase = OpenLibrary("iffparse.library",37)))
  176.     {
  177.         eprintf("Ghostscript: cannot open iffparse.library v37\n");
  178.  
  179.         exit(20);
  180.     }
  181.  
  182.     AslBase = OpenLibrary("asl.library",38);
  183. }
  184.  
  185. /* Do platform-dependent cleanup. */
  186. void
  187. gp_exit(int exit_status, int code)
  188. {
  189.     cleanup();
  190. }
  191.  
  192. /* Exit the program. */
  193. void
  194. gp_do_exit(int exit_status)
  195. {    exit(exit_status);
  196. }
  197.  
  198. /* ------ Miscellaneous ------ */
  199.  
  200. /*
  201.  * Get the string corresponding to an OS error number.
  202.  * If no string is available, return NULL.  The caller may assume
  203.  * the string is allocated statically and permanently.
  204.  */
  205. const char *
  206. gp_strerror(int errnum)
  207. {    return (strerror(errnum));
  208. }
  209.  
  210. /* ------ Date and time ------ */
  211.  
  212. /* Read the current time (in seconds since Jan. 1, 1970) */
  213. /* and fraction (in nanoseconds). */
  214. void
  215. gp_get_realtime(long *pdt)
  216. {
  217. #if defined(IXEMUL)
  218.     struct timeval tp;
  219.  
  220.  #if gettimeofday_no_timezone            /* older versions of SVR4 */
  221.     {    if ( gettimeofday(&tp) == -1 )
  222.           {    lprintf("Ghostscript: gettimeofday failed!\n");
  223.             gs_exit(1);
  224.           }
  225.     }
  226.  #else                        /* All other systems */
  227.     {    struct timezone tzp;
  228.         if ( gettimeofday(&tp, &tzp) == -1 )
  229.           {    lprintf("Ghostscript: gettimeofday failed!\n");
  230.             gs_exit(1);
  231.           }
  232.     }
  233.  #endif
  234.     /* tp.tv_sec is #secs since Jan 1, 1970 */
  235.     pdt[0] = tp.tv_sec;
  236.  
  237.     /* Some Unix systems (e.g., Interactive 3.2 r3.0) return garbage */
  238.     /* in tp.tv_usec.  Try to filter out the worst of it here. */
  239.     pdt[1] = tp.tv_usec >= 0 && tp.tv_usec < 1000000 ? tp.tv_usec*1000 : 0;
  240.  
  241. #else
  242.     LONG secs, micros;
  243.  
  244.     CurrentTime(&secs, µs);
  245.  
  246.     pdt[0] = secs;
  247.     pdt[1] = micros*1000;
  248.  
  249. #endif
  250. #ifdef DEBUG_CLOCK
  251.     printf("tp.tv_sec = %d  tp.tv_usec = %d  pdt[0] = %ld  pdt[1] = %ld\n",
  252.         tp.tv_sec, tp.tv_usec, pdt[0], pdt[1]);
  253. #endif
  254. }
  255.  
  256. /* Read the current user CPU time (in seconds) */
  257. /* and fraction (in nanoseconds).  */
  258. void
  259. gp_get_usertime(long *pdt)
  260. {
  261. #if use_times_for_usertime
  262.     LONG secs, micros;
  263.  
  264.     CurrentTime(&secs, µs);
  265.  
  266.     pdt[0] = secs;
  267.     pdt[1] = micros*1000;
  268. #else
  269.     gp_get_realtime(pdt);    /* Use an approximation on other hosts.  */
  270. #endif
  271. }
  272.  
  273. /* ------ Screen management ------ */
  274.  
  275. /* Get the environment variable that specifies the display to use. */
  276. const char *
  277. gp_getenv_display(void)
  278. {    return getenv("DISPLAY");
  279. }
  280.  
  281. /* ------ Printer accessing ------ */
  282.  
  283. /* Open a connection to a printer.  A null file name means use the */
  284. /* standard printer connected to the machine, if any. */
  285. /* "|command" opens an output pipe. */
  286. /* Return NULL if the connection could not be opened. */
  287. FILE *
  288. gp_open_printer(char *fname, int binary_mode)
  289. {
  290. #ifndef IXEMUL
  291.     return
  292.       (strlen(fname) == 0 ?
  293.        gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "w") :
  294.        fname[0] == '|' ?
  295.        NULL :
  296.        fopen(fname, "w"));
  297. #else
  298.     return
  299.       (strlen(fname) == 0 ?
  300.        gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "w") :
  301.        fname[0] == '|' ?
  302.        popen(fname + 1, "w") :
  303.        fopen(fname, "w"));
  304. #endif
  305. }
  306.  
  307. /* Close the connection to the printer. */
  308. void
  309. gp_close_printer(FILE *pfile, const char *fname)
  310. {
  311. #ifndef IXEMUL
  312.     fclose(pfile);
  313. #else
  314.     if ( fname[0] == '|' )
  315.         pclose(pfile);
  316.     else
  317.         fclose(pfile);
  318. #endif
  319. }
  320.  
  321. /* ------ File name syntax ------ */
  322.  
  323. /* Define the character used for separating file names in a list. */
  324. const char gp_file_name_list_separator = ',';
  325.  
  326. /* Define the string to be concatenated with the file mode */
  327. /* for opening files without end-of-line conversion. */
  328. const char gp_fmode_binary_suffix[] = "";
  329. /* Define the file modes for binary reading or writing. */
  330. const char gp_fmode_rb[] = "r";
  331. const char gp_fmode_wb[] = "w";
  332.  
  333. /* Answer whether a file name contains a directory/device specification, */
  334. /* i.e. is absolute (not directory- or device-relative). */
  335. int
  336. gp_file_name_is_absolute(const char *fname, uint len)
  337. {
  338.     int i;
  339.  
  340.     for(i = 0 ; i < len ; i++)
  341.     {
  342.         if(fname[i] == ':')
  343.             return(1);
  344.     }
  345.  
  346.     return(0);
  347. }
  348.  
  349. /* Answer the string to be used for combining a directory/device prefix */
  350. /* with a base file name.  The file name is known to not be absolute. */
  351. const char *
  352. gp_file_name_concat_string(const char *prefix, uint plen, const char *fname, uint len)
  353. {
  354. #ifdef IXEMUL
  355.     if(plen > 0 && (prefix[plen - 1] == '/' || prefix[plen - 1] == ':'))
  356.         return("");
  357.     else
  358.         return("/");
  359. #else
  360.     if(plen > 0)
  361.         if(prefix[plen - 1] == '/' || prefix[plen - 1] == ':')
  362.             return("");
  363.         else
  364.             return("/");
  365.     else
  366.         return("");
  367. #endif
  368. }
  369.  
  370. /* ------ File naming and accessing ------ */
  371.  
  372. /* Define the default scratch file name prefix. */
  373. const char gp_scratch_file_name_prefix[] = "T:gs_";
  374.  
  375. /* Define the name of the null output file. */
  376. #ifdef IXEMUL
  377. const char gp_null_file_name[] = "/dev/null";
  378. #else
  379. const char gp_null_file_name[] = "NIL:";
  380. #endif
  381.  
  382. /* Define the name that designates the current directory. */
  383. #ifdef IXEMUL
  384. const char gp_current_directory_name[] = ".";
  385. #else
  386. const char gp_current_directory_name[] = "";
  387. #endif
  388.  
  389. /* Create and open a scratch file with a given name prefix. */
  390. /* Write the actual file name at fname. */
  391. FILE *
  392. gp_open_scratch_file(const char *prefix, char *fname, const char *mode)
  393. {
  394. #ifndef IXEMUL
  395.     char *temp;
  396.     char temp2[100];
  397.     struct Task *thistask;
  398.     LONG secs, micros;
  399. #endif
  400.  
  401.     strcpy(fname,prefix);
  402.     /* Prevent trailing X's in path from being converted by mktemp. */
  403.     if ( *fname != 0 && fname[strlen(fname) - 1] == 'X' )
  404.         strcat(fname, "-");
  405. #ifdef IXEMUL
  406.     strcat(fname, "XXXXXX");
  407. #else
  408.     CurrentTime(&secs, µs);
  409.     sprintf(temp2,"%lx",FindTask(NULL));
  410.     strcat(fname, temp2);
  411. #endif
  412. #ifdef IXEMUL
  413.     mktemp(fname);
  414. #endif
  415.     return fopen(fname, mode);
  416. }
  417.  
  418. /* Open a file with the given name, as a stream of uninterpreted bytes. */
  419. FILE *
  420. gp_fopen(const char *fname, const char *mode)
  421. {    return fopen(fname, mode);
  422. }
  423.  
  424. /* ------ File enumeration ------ */
  425.  
  426. /* Thanks to Fritz Elfert (Fritz_Elfert@wue.maus.de) for */
  427. /* the original version of the following code, and Richard Mlynarik */
  428. /* (mly@adoc.xerox.com) for an improved version. */
  429.  
  430. typedef struct dirstack_s dirstack;
  431. struct dirstack_s {
  432.     dirstack *next;
  433.     DIR *entry;
  434. };
  435. gs_private_st_ptrs1(st_dirstack, dirstack, "dirstack",
  436.   dirstack_enum_ptrs, dirstack_reloc_ptrs, next);
  437.  
  438. struct file_enum_s {
  439.     DIR *dirp;        /* pointer to current open directory   */
  440.     char *pattern;        /* original pattern                    */
  441.     char *work;        /* current path                        */
  442.     int worklen;            /* strlen (work)               */
  443.     dirstack *dstack;    /* directory stack                     */
  444.     int patlen;
  445.     int pathead;            /* how much of pattern to consider
  446.                  *  when listing files in current directory */
  447.     bool first_time;
  448.     gs_memory_t *memory;
  449. };
  450. gs_private_st_ptrs3(st_file_enum, struct file_enum_s, "file_enum",
  451.   file_enum_enum_ptrs, file_enum_reloc_ptrs, pattern, work, dstack);
  452.  
  453. /* Private procedures */
  454.  
  455. /* Do a wild-card match. */
  456. #ifdef DEBUG
  457. private bool
  458. wmatch(const byte *str, uint len, const byte *pstr, uint plen,
  459.   const string_match_params *psmp)
  460. {    bool match = string_match(str, len, pstr, plen, psmp);
  461.     if ( gs_debug_c('e') )
  462.       { dputs("[e]string_match(\"");
  463.         fwrite(str, 1, len, dstderr);
  464.         dputs("\", \"");
  465.         fwrite(pstr, 1, plen, dstderr);
  466.         dprintf1("\") = %s\n", (match ? "TRUE" : "false"));
  467.       }
  468.     return match;
  469. }
  470. #define string_match wmatch
  471. #endif
  472.  
  473. /* Search a string backward for a character. */
  474. /* (This substitutes for strrchr, which some systems don't provide.) */
  475. private char *
  476. rchr(char *str, char ch, int len)
  477. {    register char *p = str + len;
  478.     while ( p > str )
  479.       if ( *--p == ch ) return p;
  480.     return 0;
  481. }
  482.  
  483. /* Pop a directory from the enumeration stack. */
  484. private bool
  485. popdir(file_enum *pfen)
  486. {    dirstack *d = pfen->dstack;
  487.     if ( d == 0 )
  488.       return false;
  489.     pfen->dirp = d->entry;
  490.     pfen->dstack = d->next;
  491.     gs_free_object(pfen->memory, d, "gp_enumerate_files(popdir)");
  492.     return true;
  493. }
  494.  
  495. /* Initialize an enumeration. */
  496. file_enum *
  497. gp_enumerate_files_init(const char *pat, uint patlen, gs_memory_t *mem)
  498. {    file_enum *pfen;
  499.     char *p;
  500.     char *work;
  501.  
  502.     /* Reject attempts to enumerate paths longer than the */
  503.     /* system-dependent limit. */
  504.     if ( patlen > MAXPATHLEN )
  505.         return 0;
  506.  
  507.     /* Reject attempts to enumerate with a pattern containing zeroes. */
  508.     {    const char *p1;
  509.         for (p1 = pat; p1 < pat + patlen; p1++)
  510.             if (*p1 == 0) return 0;
  511.     }
  512.         /* >>> Should crunch strings of repeated "/"'s in pat to a single "/"
  513.          * >>>  to match stupid unix filesystem "conventions" */
  514.  
  515.     pfen = gs_alloc_struct(mem, file_enum, &st_file_enum,
  516.                    "gp_enumerate_files");
  517.     if (pfen == 0)
  518.         return 0;
  519.  
  520.     /* pattern and work could be allocated as strings, */
  521.     /* but it's simpler for GC and freeing to allocate them as bytes. */
  522.  
  523.     pfen->pattern =
  524.       (char *)gs_alloc_bytes(mem, patlen + 1,
  525.                  "gp_enumerate_files(pattern)");
  526.     if (pfen->pattern == 0)
  527.         return 0;
  528.     memcpy(pfen->pattern, pat, patlen);
  529.     pfen->pattern[patlen] = 0;
  530.  
  531.     work = (char *)gs_alloc_bytes(mem, MAXPATHLEN+1,
  532.                       "gp_enumerate_files(work)");
  533.     if (work == 0)
  534.         return 0;
  535.     pfen->work = work;
  536.  
  537.     p = work;
  538.     memcpy(p, pat, patlen);
  539.     p += patlen;
  540.     *p = 0;
  541.  
  542.     /* Remove directory specifications beyond the first wild card. */
  543.     /* Some systems don't have strpbrk, so we code it open. */
  544.     p = pfen->work;
  545.     while ( !(*p == '*' || *p == '?' || *p == 0) ) p++;
  546.     while ( !(*p == '/' || *p == 0) ) p++;
  547.     if ( *p == '/' )
  548.       *p = 0;
  549.         /* Substring for first wildcard match */
  550.         pfen->pathead = p - work;
  551.  
  552.     /* Select the next higher directory-level. */
  553.         p = rchr(work, '/', p - work);
  554.         if (!p)
  555.       {    /* No directory specification */
  556.         work[0] = 0;
  557.         pfen->worklen = 0;
  558.       }
  559.         else
  560.       {    if (p == work)
  561.           {    /* Root directory -- don't turn "/" into "" */
  562.             p++;
  563.           }
  564.         *p = 0;
  565.         pfen->worklen = p - work;
  566.       }
  567.  
  568.     pfen->memory = mem;
  569.     pfen->dstack = 0;
  570.     pfen->first_time = true;
  571.     pfen->patlen = patlen;
  572.     return pfen;
  573. }
  574.  
  575. /* Enumerate the next file. */
  576. uint
  577. gp_enumerate_files_next(file_enum *pfen, char *ptr, uint maxlen)
  578. {    dir_entry *de;
  579.     char *work = pfen->work;
  580.     int worklen = pfen->worklen;
  581.     char *pattern = pfen->pattern;
  582.     int pathead = pfen->pathead;
  583.     int len;
  584.     struct stat stbuf;
  585.  
  586.     if ( pfen->first_time )
  587.       {    pfen->dirp = ((worklen == 0) ? opendir(".") : opendir(work));
  588.         if_debug1('e', "[e]file_enum:First-Open '%s'\n", work);
  589.         pfen->first_time = false;
  590.         if (pfen->dirp == 0)    /* first opendir failed */
  591.           {    gp_enumerate_files_close(pfen);
  592.             return ~(uint)0;
  593.           }
  594.       }
  595.  
  596.  top:    de = readdir(pfen->dirp);
  597.     if (de == 0)
  598.       {    /* No more entries in this directory */
  599.         char *p;
  600.  
  601.         if_debug0('e', "[e]file_enum:Closedir\n");
  602.         closedir(pfen->dirp);
  603.         /* Back working directory and matching pattern up one level */
  604.         p = rchr(work,'/', worklen);
  605.         if (p != 0)
  606.           {    if (p == work) p++;
  607.             *p = 0;
  608.             worklen = p - work;
  609.           }
  610.                 else
  611.                   worklen = 0;
  612.         p = rchr(pattern,'/', pathead);
  613.         if (p != 0)
  614.           pathead = p - pattern;
  615.         else
  616.           pathead = 0;
  617.  
  618.         if (popdir(pfen))
  619.           {    /* Back up the directory tree. */
  620.             if_debug1('e', "[e]file_enum:Dir popped '%s'\n", work);
  621.             goto top;
  622.           }
  623.         else
  624.           {    if_debug0('e', "[e]file_enum:Dirstack empty\n");
  625.             gp_enumerate_files_close(pfen);
  626.             return ~(uint)0;
  627.           }
  628.       }
  629.  
  630.     /* Skip . and .. */
  631.     len = strlen(de->d_name);
  632.     if (len <= 2 && (!strcmp(de->d_name,".") || !strcmp(de->d_name,"..") ))
  633.       goto top;
  634.     if (len + worklen + 1 > MAXPATHLEN)
  635.       /* Should be an error, I suppose */
  636.       goto top;
  637.     if (worklen == 0)
  638.       {    /* "Current" directory (evil un*x kludge) */
  639.         memcpy(work, de->d_name, len + 1);
  640.       }
  641.     else if (worklen == 1 && work[0] == '/')
  642.       {    /* Root directory */
  643.         memcpy(work + 1, de->d_name, len + 1);
  644.         len = len + 1;
  645.       }
  646.     else
  647.       {    work[worklen] = '/';
  648.         memcpy(work + worklen + 1, de->d_name, len + 1);
  649.         len = worklen + 1 + len;
  650.       }
  651.  
  652.     /* Test for a match at this directory level */
  653.     if (!string_match((byte *)work, len, (byte *)pattern, pathead, NULL))
  654.       goto top;
  655.  
  656.     /* Perhaps descend into subdirectories */
  657.     if (pathead < pfen->patlen)
  658.       {    DIR *dp;
  659.  
  660.         if (((stat(work,&stbuf) >= 0)
  661.              ? !stat_is_dir(stbuf)
  662.              /* Couldn't stat it.
  663.               * Well, perhaps it's a directory and
  664.               * we'll be able to list it anyway.
  665.               * If it isn't or we can't, no harm done. */
  666.              : 0))
  667.           goto top;
  668.  
  669.         if (pfen->patlen == pathead + 1)
  670.           {    /* Listing "foo/?/" -- return this entry */
  671.             /* if it's a directory. */
  672.             if (!stat_is_dir (stbuf))
  673.               {    /* Do directoryp test the hard way */
  674.                 dp = opendir(work);
  675.                 if (!dp) goto top;
  676.                 closedir(dp);
  677.               }
  678.             work[len++] = '/';
  679.             goto winner;
  680.           }
  681.  
  682.         /* >>> Should optimise the case in which the next level */
  683.         /* >>> of directory has no wildcards. */
  684.         dp = opendir(work);
  685. #ifdef DEBUG
  686.         {    char save_end = pattern[pathead];
  687.             pattern[pathead] = 0;
  688.             if_debug2('e', "[e]file_enum:fname='%s', p='%s'\n",
  689.                   work, pattern);
  690.             pattern[pathead] = save_end;
  691.         }
  692. #endif /* DEBUG */
  693.         if (!dp)
  694.           /* Can't list this one */
  695.           goto top;
  696.         else
  697.           {    /* Advance to the next directory-delimiter */
  698.             /* in pattern */
  699.             char *p;
  700.                         dirstack *d;
  701.             for (p = pattern + pathead + 1; ; p++)
  702.               {    if (*p == 0)
  703.                   {    /* No more subdirectories to match */
  704.                     pathead = pfen->patlen;
  705.                     break;
  706.                   }
  707.                 else if (*p == '/')
  708.                   {    pathead = p - pattern;
  709.                     break;
  710.                   }
  711.               }
  712.  
  713.                         /* Push a directory onto the enumeration stack. */
  714.                         d = gs_alloc_struct(pfen->memory, dirstack,
  715.                                             &st_dirstack,
  716.                                             "gp_enumerate_files(pushdir)");
  717.                         if ( d != 0 )
  718.                         {
  719.                           d->next  = pfen->dstack;
  720.                           d->entry = pfen->dirp;
  721.                           pfen->dstack = d;
  722.                         }
  723.                         else
  724.                           DO_NOTHING; /* >>> e_VMerror!!! */
  725.  
  726.             if_debug1('e', "[e]file_enum:Dir pushed '%s'\n",
  727.                   work);
  728.             worklen = len;
  729.             pfen->dirp = dp;
  730.             goto top;
  731.           }
  732.       }
  733.  
  734.  winner:
  735.     /* We have a winner! */
  736.     pfen->worklen = worklen;
  737.     pfen->pathead = pathead;
  738.     memcpy(ptr, work, len);
  739.     return len;
  740. }
  741.  
  742. /* Clean up the file enumeration. */
  743. void
  744. gp_enumerate_files_close(file_enum *pfen)
  745. {    gs_memory_t *mem = pfen->memory;
  746.  
  747.     if_debug0('e', "[e]file_enum:Cleanup\n");
  748.     while (popdir(pfen))    /* clear directory stack */
  749.           DO_NOTHING;
  750.     gs_free_object(mem, (byte *)pfen->work,
  751.                "gp_enumerate_close(work)");
  752.     gs_free_object(mem, (byte *)pfen->pattern,
  753.                "gp_enumerate_files_close(pattern)");
  754.     gs_free_object(mem, pfen, "gp_enumerate_files_close");
  755. }
  756.  
  757. /***************************************************************************/
  758. /*         Functions from ixemul.library source which aren't in Libnix     */
  759. /***************************************************************************/
  760. #ifndef IXEMUL
  761.  
  762. /***************************************************************************/
  763. /*                                     modf.c                              */
  764. /***************************************************************************/
  765. #include <proto/mathieeedoubbas.h>
  766.  
  767. /*
  768.  * modf(value, iptr): return fractional part of value, and stores the
  769.  * integral part into iptr (a pointer to double).
  770.  */
  771.  
  772. double
  773. modf (double value, double *iptr)
  774. {
  775.   /* if value negative */
  776.   if (IEEEDPTst (value) < 0)
  777.     {
  778.       /* in that case, the integer part is calculated by ceil() */
  779.       *iptr = IEEEDPCeil (value);
  780.       return IEEEDPSub (*iptr, value);
  781.     }
  782.   else
  783.     {
  784.  
  785.       /* if positive, we go for the floor() */
  786.       *iptr = IEEEDPFloor (value);
  787.       return IEEEDPSub (value, *iptr);
  788.     }
  789. }
  790. /***************************************************************************/
  791. /*                                     frexp.c                             */
  792. /***************************************************************************/
  793. #if defined(LIBC_SCCS) && !defined(lint)
  794. static char sccsid[] = "@(#)frexp.c    5.2 (Berkeley) 3/9/86";
  795. #endif LIBC_SCCS and not lint
  796.  
  797. #define KERNEL
  798. /*#include "ixemul.h"*/
  799.  
  800. /*
  801.  *    the call
  802.  *        x = frexp(arg,&exp);
  803.  *    must return a double fp quantity x which is <1.0
  804.  *    and the corresponding binary exponent "exp".
  805.  *    such that
  806.  *        arg = x*2^exp
  807.  *    if the argument is 0.0, return 0.0 mantissa and 0 exponent.
  808.  */
  809.  
  810. double
  811. frexp(double x, int *i)
  812. {
  813.   int neg;
  814.   int j;
  815.  
  816.   j = 0;
  817.   neg = 0;
  818.  
  819.   if (x < 0)
  820.     {
  821.       x = -x;
  822.       neg = 1;
  823.     }
  824.  
  825.   if (x >= 1.0)
  826.     while(x >= 1.0)
  827.       {
  828.     j = j+1;
  829.     x = x/2;
  830.       }
  831.   else if(x < 0.5 && x != 0.0)
  832.     while(x < 0.5)
  833.       {
  834.     j = j-1;
  835.     x = 2*x;
  836.       }
  837.  
  838.   *i = j;
  839.   if (neg) x = -x;
  840.   return x;
  841. }
  842.  
  843. /***************************************************************************/
  844. /*                                     ldexp.c                             */
  845. /***************************************************************************/
  846. /*
  847.  * ldexp returns the quanity "value" * 2 ^ "exp"
  848.  *
  849.  * For the mc68000 using IEEE format the double precision word format is:
  850.  *
  851.  * WORD N   =>    SEEEEEEEEEEEMMMM
  852.  * WORD N+1 =>    MMMMMMMMMMMMMMMM
  853.  * WORD N+2 =>    MMMMMMMMMMMMMMMM
  854.  * WORD N+3 =>    MMMMMMMMMMMMMMMM
  855.  *
  856.  * Where:          S  =>   Sign bit
  857.  *                 E  =>   Exponent
  858.  *                 X  =>   Ignored (set to 0)
  859.  *                 M  =>   Mantissa bit
  860.  *
  861.  * NOTE:  Beware of 0.0; on some machines which use excess 128 notation for the
  862.  * exponent, if the mantissa is zero the exponent is also.
  863.  *
  864.  */
  865.  
  866. #define MANT_MASK 0x800FFFFF    /* Mantissa extraction mask     */
  867. #define ZPOS_MASK 0x3FF00000    /* Positive # mask for exp = 0  */
  868. #define ZNEG_MASK 0x3FF00000    /* Negative # mask for exp = 0  */
  869.  
  870. #define EXP_MASK 0x7FF00000    /* Mask for exponent            */
  871. #define EXP_SHIFTS 20        /* Shifts to get into LSB's     */
  872. #define EXP_BIAS 1023        /* Exponent bias                */
  873.  
  874.  
  875. union dtol
  876. {
  877.   double dval;
  878.   int ival[2];
  879. };
  880.  
  881. double
  882. ldexp (value, exp)
  883.      double value;
  884.      int exp;
  885. {
  886.   union dtol number;
  887.   int *iptr, cexp;
  888.  
  889.   if (value == 0.0)
  890.     return (0.0);
  891.   else
  892.     {
  893.       number.dval = value;
  894.       iptr = &number.ival[0];
  895.       cexp = (((*iptr) & EXP_MASK) >> EXP_SHIFTS) - EXP_BIAS;
  896.       *iptr &= ~EXP_MASK;
  897.       exp += EXP_BIAS;
  898.       *iptr |= ((exp + cexp) << EXP_SHIFTS) & EXP_MASK;
  899.       return (number.dval);
  900.     }
  901. }
  902. #endif
  903.